<!-- tab组件: <me-tabs v-model="tabIndex" :tabs="tabs" @change="tabChange"></me-tabs> -->
<template>
	<!-- 全局弹框样式 -->
	<view class="me-tabs" :class="{ 'tabs-fixed': fixed }" :style="{ height: tabHeightVal, '--fixed-top': top + 'px' }">
		<scroll-view v-if="tabs.length" :id="viewId" :scroll-left="scrollLeft" scroll-x scroll-with-animation :scroll-animation-duration="300">
			<view class="tabs-item" :class="{ 'tabs-flex': !isScroll, 'tabs-scroll': isScroll }">
				<!-- tab -->
				<view
					class="tab-item"
					:style="{ width: tabWidthVal, height: tabHeightVal, '--active-color': activeColor, 'margin-right': gutter + 'px' }"
					v-for="(tab, i) in tabs"
					:class="{ active: value === i, 'u-flex-wrap': !!tab.subName }"
					:key="i"
					@click="tabClick(i)"
				>
					<view>
						<view>{{ getTabName(tab) }}</view>
						<view v-if="tab.subName" class="u-font-24">{{ tab.subName }}</view>
					</view>
				</view>
				<!-- 下划线 -->
				<!-- <view class="tabs-line" :style="{left:lineLeft,'--active-color':activeColor,width: tabWidthVal || '100rpx'}"></view> -->
			</view>
		</scroll-view>
		<view class="inline"></view>
	</view>
</template>

<script>
export default {
	props: {
		tabs: {
			// 支持格式: ['全部', '待付款'] 或 [{name:'全部'}, {name:'待付款'}]
			type: Array,
			default() {
				return [];
			}
		},
		nameKey: {
			// 取name的字段
			type: String,
			default: 'name'
		},
		value: {
			// 当前显示的下标 (使用v-model语法糖: 1.props需为value; 2.需回调input事件)
			type: [String, Number],
			default: 0
		},
		fixed: Boolean, // 是否悬浮,默认false
		tabWidth: Number, // 每个tab的宽度,默认不设置值,为flex平均分配; 如果指定宽度,则不使用flex,每个tab居左,超过则水平滑动(单位默认rpx)
		height: {
			// 高度,单位rpx
			type: Number,
			default: 64
		},
		top: {
			type: Number,
			default: 0
		},
		activeColor: {
			type: String,
			default: 'red'
		},
		gutter: {
			type: Number,
			default: 0
		}
	},
	data() {
		return {
			viewId:
				'id_' +
				Math.random()
					.toString(36)
					.substr(2, 16),
			scrollLeft: 0
		};
	},
	computed: {
		isScroll() {
			return this.tabWidth && this.tabs.length; // 指定了tabWidth的宽度,则支持水平滑动
		},
		tabHeightPx() {
			return uni.upx2px(this.height);
		},
		tabHeightVal() {
			return this.tabHeightPx + 'px';
		},
		tabWidthPx() {
			return uni.upx2px(this.tabWidth);
		},
		tabWidthVal() {
			return this.isScroll ? this.tabWidthPx + 'px' : '';
		},
		lineLeft() {
			if (this.isScroll) {
				return this.tabWidthPx * this.value + this.tabWidthPx / 2 + this.gutter * this.value + 'px'; // 需转为px (用rpx的话iOS真机显示有误差)
			} else {
				return (100 / this.tabs.length) * (this.value + 1) - 100 / (this.tabs.length * 2) + '%';
			}
		}
	},
	watch: {
		tabs() {
			this.warpWidth = null; // 重新计算容器宽度
			this.scrollCenter(); // 水平滚动到中间
		},
		value() {
			this.scrollCenter(); // 水平滚动到中间
		}
	},
	methods: {
		getTabName(tab) {
			return typeof tab === 'object' ? tab[this.nameKey] : tab;
		},
		tabClick(i) {
			if (this.value != i) {
				this.$emit('input', i);
				this.$emit('change', i);
			}
		},
		async scrollCenter() {
			if (!this.isScroll) return;
			if (!this.warpWidth) {
				// tabs容器的宽度
				let rect = await this.initWarpRect();
				this.warpWidth = rect ? rect.width : uni.getSystemInfoSync().windowWidth; // 某些情况下取不到宽度,暂时取屏幕宽度
			}
			let tabLeft = this.tabWidthPx * this.value + this.tabWidthPx / 2; // 当前tab中心点到左边的距离
			let diff = tabLeft - this.warpWidth / 2; // 如果超过tabs容器的一半,则滚动差值
			this.scrollLeft = diff;
			// #ifdef MP-TOUTIAO
			this.scrollTimer && clearTimeout(this.scrollTimer);
			this.scrollTimer = setTimeout(() => {
				// 字节跳动小程序,需延时再次设置scrollLeft,否则tab切换跨度较大时不生效
				this.scrollLeft = Math.ceil(diff);
			}, 400);
			// #endif
		},
		initWarpRect() {
			return new Promise(resolve => {
				setTimeout(() => {
					// 延时确保dom已渲染, 不使用$nextclick
					let query = uni.createSelectorQuery();
					// #ifndef MP-ALIPAY
					query = query.in(this); // 支付宝小程序不支持in(this),而字节跳动小程序必须写in(this), 否则都取不到值
					// #endif
					query
						.select('#' + this.viewId)
						.boundingClientRect(data => {
							resolve(data);
						})
						.exec();
				}, 20);
			});
		}
	},
	mounted() {
		this.scrollCenter(); // 滚动到当前下标
		this.$nextTick(() => {
			let query = uni.createSelectorQuery();
			// #ifndef MP-ALIPAY
			query = query.in(this); // 支付宝小程序不支持in(this),而字节跳动小程序必须写in(this), 否则都取不到值
			// #endif
			query
				.select('.me-tabs')
				.boundingClientRect(data => {
					this.$emit('tabTop', data);
				})
				.exec();
		});
	}
};
</script>

<style lang="scss">
.me-tabs {
	position: relative;
	font-size: 32rpx;
	box-sizing: border-box;
	overflow-y: hidden;
	&.tabs-fixed {
		z-index: 990;
		position: fixed;
		top: calc(var(--status-bar-height) + var(--fixed-top));
		left: 0;
		width: 100%;
	}

	.tabs-item {
		position: relative;
		white-space: nowrap;
		padding-bottom: 30rpx; // 撑开高度,再配合me-tabs的overflow-y: hidden,以达到隐藏滚动条的目的
		box-sizing: border-box;
		color: #8f94a5;
		.tab-item {
			position: relative;
			text-align: center;
			box-sizing: border-box;
			font-size: 34rpx;
			color: var(--title-color);
			font-weight: 500;
			&:last-child {
				margin-right: 0;
			}
			&.active {
				color: var(--active-color);
				font-weight: bold;
			}
		}
	}

	// 平分的方式显示item
	.tabs-flex {
		display: flex;
		.tab-item {
			margin-left: 120rpx;
			margin-top: 10rpx;
		}
	}
	// 居左显示item,支持水平滑动
	.tabs-scroll {
		.tab-item {
			display: inline-flex;
		}
	}

	// 选中tab的线
	.tabs-line {
		z-index: 1;
		position: absolute;
		bottom: 30rpx; // 至少与.tabs-item的padding-bottom一致,才能保证在底部边缘
		height: 4rpx;
		transform: translateX(-50%);
		border-radius: 2rpx;
		transition: left 0.3s;
		background: var(--active-color);
	}
}

.inline {
	// 一根线
	width: 100%;
	border: 1rpx #f0f1f5 solid;
	position: relative;
	top: -42rpx;
}
</style>
